#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""PDF处理工具函数"""

import re
import logging
from typing import List, Dict, Any, Optional, Tuple, Union

# 创建日志记录器
logger = logging.getLogger(__name__)

def clean_table_data(table: List[List[Any]]) -> List[List[Any]]:
    """清理表格数据
    
    Args:
        table: 原始表格数据
        
    Returns:
        清理后的表格数据
    """
    if not table:
        return []
    
    # 移除空行
    cleaned_table = []
    for row in table:
        # 检查行是否为空（所有单元格都为None或空字符串）
        if any(cell is not None and str(cell).strip() != "" for cell in row):
            # 清理每个单元格
            cleaned_row = [clean_cell(cell) for cell in row]
            cleaned_table.append(cleaned_row)
    
    return cleaned_table

def clean_cell(cell: Any) -> str:
    """清理单元格数据
    
    Args:
        cell: 单元格数据
        
    Returns:
        清理后的单元格文本
    """
    if cell is None:
        return ""
    
    # 转换为字符串
    cell_str = str(cell).strip()
    
    # 移除多余空格
    cell_str = re.sub(r'\s+', '', cell_str)
    
    # 移除特殊字符
    cell_str = cell_str.replace('\r', '').replace('\n', '')
    
    return cell_str

def detect_table_structure(table: List[List[Any]]) -> Dict[str, Any]:
    """检测表格结构
    
    Args:
        table: 表格数据
        
    Returns:
        表格结构信息
    """
    if not table or len(table) == 0:
        return {"type": "unknown", "structure": "empty"}
    
    # 获取表格维度
    rows = len(table)
    cols = len(table[0]) if rows > 0 else 0
    
    # 检测表头
    has_header = detect_header(table)
    
    # 检测表格类型
    table_type = detect_table_type(table)
    
    # 检测数据列类型
    column_types = detect_column_types(table) if rows > 1 else []
    
    # 构建结构信息
    structure = {
        "type": table_type,
        "rows": rows,
        "cols": cols,
        "has_header": has_header,
        "column_types": column_types,
        "empty_cells": count_empty_cells(table),
        "merged_cells_likely": detect_merged_cells(table),
    }
    
    return structure

def detect_header(table: List[List[Any]]) -> bool:
    """检测表格是否有表头
    
    Args:
        table: 表格数据
        
    Returns:
        是否有表头
    """
    if not table or len(table) < 2:
        return False
    
    # 表头通常是第一行，与其他行格式不同
    header_row = table[0]
    data_row = table[1]
    
    # 检查第一行是否包含列名特征
    header_features = 0
    data_features = 0
    
    for cell in header_row:
        cell_str = str(cell).strip() if cell else ""
        # 表头单元格通常较短
        if len(cell_str) < 20:
            header_features += 1
        # 表头通常不包含数字或只有序号
        if not re.search(r'\d+\.\d+', cell_str):
            header_features += 1
    
    for cell in data_row:
        cell_str = str(cell).strip() if cell else ""
        # 数据行通常包含数字
        if re.search(r'\d', cell_str):
            data_features += 1
    
    # 如果表头特征明显多于数据特征，认为有表头
    return header_features > data_features

def detect_table_type(table: List[List[Any]]) -> str:
    """检测表格类型
    
    Args:
        table: 表格数据
        
    Returns:
        表格类型
    """
    if not table or len(table) == 0:
        return "unknown"
    
    # 检查是否是财务报表
    financial_keywords = ["资产", "负债", "利润", "损益", "现金流量", "收入", "支出", "成本", "费用"]
    tax_keywords = ["税", "纳税", "税额", "税率", "税基", "税种", "增值税", "所得税", "消费税"]
    
    # 统计关键词出现次数
    financial_count = 0
    tax_count = 0
    
    for row in table:
        for cell in row:
            cell_str = str(cell).strip() if cell else ""
            for keyword in financial_keywords:
                if keyword in cell_str:
                    financial_count += 1
            for keyword in tax_keywords:
                if keyword in cell_str:
                    tax_count += 1
    
    # 根据关键词判断表格类型
    if financial_count > 3:
        return "financial_statement"
    elif tax_count > 3:
        return "tax_form"
    elif financial_count > 0 and tax_count > 0:
        return "financial_tax_mixed"
    
    # 检查是否是列表型表格
    if len(table) > 3 and all(len(row) == len(table[0]) for row in table):
        return "list_table"
    
    # 默认类型
    return "general"

def detect_column_types(table: List[List[Any]]) -> List[str]:
    """检测表格列的数据类型
    
    Args:
        table: 表格数据
        
    Returns:
        列数据类型列表
    """
    if not table or len(table) < 2:
        return []
    
    # 假设第一行是表头
    data_rows = table[1:]
    num_cols = len(table[0])
    column_types = ["unknown"] * num_cols
    
    # 对每一列进行类型检测
    for col_idx in range(num_cols):
        # 收集该列的所有非空值
        col_values = [row[col_idx] for row in data_rows if col_idx < len(row) and row[col_idx]]
        
        if not col_values:
            column_types[col_idx] = "empty"
            continue
        
        # 检测数值类型
        numeric_count = 0
        date_count = 0
        text_count = 0
        
        for value in col_values:
            value_str = str(value).strip()
            
            # 检测数值
            if re.match(r'^-?\d+(\.\d+)?$', value_str):
                numeric_count += 1
            # 检测日期
            elif re.match(r'^\d{4}[-/年]\d{1,2}[-/月]\d{1,2}日?$', value_str):
                date_count += 1
            # 其他视为文本
            else:
                text_count += 1
        
        # 根据占比确定列类型
        total = numeric_count + date_count + text_count
        if total == 0:
            column_types[col_idx] = "empty"
        elif numeric_count / total > 0.7:
            column_types[col_idx] = "numeric"
        elif date_count / total > 0.7:
            column_types[col_idx] = "date"
        else:
            column_types[col_idx] = "text"
    
    return column_types

def count_empty_cells(table: List[List[Any]]) -> int:
    """统计表格中的空单元格数量
    
    Args:
        table: 表格数据
        
    Returns:
        空单元格数量
    """
    empty_count = 0
    
    for row in table:
        for cell in row:
            if cell is None or str(cell).strip() == "":
                empty_count += 1
    
    return empty_count

def detect_merged_cells(table: List[List[Any]]) -> bool:
    """检测表格是否可能包含合并单元格
    
    Args:
        table: 表格数据
        
    Returns:
        是否可能包含合并单元格
    """
    if not table or len(table) < 2:
        return False
    
    # 检查行长度是否一致
    row_lengths = [len(row) for row in table]
    if len(set(row_lengths)) > 1:
        return True
    
    # 检查重复单元格模式（可能是合并单元格的特征）
    for row_idx in range(len(table)):
        for col_idx in range(1, len(table[row_idx])):
            if col_idx < len(table[row_idx]) and row_idx < len(table) and \
               table[row_idx][col_idx] == table[row_idx][col_idx-1] and \
               table[row_idx][col_idx] is not None and \
               str(table[row_idx][col_idx]).strip() != "":
                return True
    
    return False

def extract_table_title(page_text: str, table_bbox: Tuple[float, float, float, float]) -> Optional[str]:
    """从页面文本中提取表格标题
    
    Args:
        page_text: 页面文本
        table_bbox: 表格边界框 (x0, y0, x1, y1)
        
    Returns:
        表格标题或None
    """
    if not page_text or not table_bbox:
        return None
    
    # 将页面文本分割成行
    lines = page_text.split('\n')
    
    # 表格标题通常在表格上方
    table_top = table_bbox[1]  # y0坐标
    
    # 查找可能的表格标题
    title_patterns = [
        r'表\s*\d+[\s\S]*',  # 匹配"表1 xxx"、"表 2 xxx"等
        r'表\s*[一二三四五六七八九十]+[\s\S]*',  # 匹配"表一 xxx"、"表 二 xxx"等
        r'[Tt]able\s*\d+[\s\S]*',  # 匹配英文表格标题
    ]
    
    # 在表格上方查找标题
    for line in lines:
        # 检查是否匹配表格标题模式
        for pattern in title_patterns:
            if re.match(pattern, line):
                return line.strip()
    
    # 如果没有找到明确的标题，返回None
    return None

def get_text_above_table(page, table_bbox: Tuple[float, float, float, float], max_distance: float = 50) -> str:
    """获取表格上方的文本
    
    Args:
        page: pdfplumber页面对象
        table_bbox: 表格边界框 (x0, y0, x1, y1)
        max_distance: 最大距离
        
    Returns:
        表格上方的文本
    """
    if not page or not table_bbox:
        return ""
    
    # 表格上方区域的边界框
    x0, y0, x1, y1 = table_bbox
    above_bbox = (x0, y0 - max_distance, x1, y0)
    
    # 提取上方区域的文本
    try:
        above_text = page.crop(above_bbox).extract_text() or ""
        return above_text.strip()
    except Exception as e:
        logger.warning(f"获取表格上方文本失败: {str(e)}")
        return ""

def is_table_continued(table: List[List[Any]], prev_table: List[List[Any]]) -> bool:
    """判断表格是否是前一个表格的续表
    
    Args:
        table: 当前表格
        prev_table: 前一个表格
        
    Returns:
        是否是续表
    """
    if not table or not prev_table:
        return False
    
    # 检查列数是否相同
    if len(table[0]) != len(prev_table[0]):
        return False
    
    # 检查表头是否相似
    if len(table) > 0 and len(prev_table) > 0:
        header_similarity = compare_headers(table[0], prev_table[0])
        if header_similarity > 0.7:  # 如果表头相似度大于70%
            return True
    
    return False

def compare_headers(header1: List[Any], header2: List[Any]) -> float:
    """比较两个表头的相似度
    
    Args:
        header1: 第一个表头
        header2: 第二个表头
        
    Returns:
        相似度 (0-1)
    """
    if not header1 or not header2 or len(header1) != len(header2):
        return 0.0
    
    # 计算相同单元格的比例
    same_cells = sum(1 for a, b in zip(header1, header2) if str(a).strip() == str(b).strip())
    similarity = same_cells / len(header1) if len(header1) > 0 else 0
    
    return similarity

def extract_table_with_merged_cells(page, table_bbox: Tuple[float, float, float, float]) -> List[List[Any]]:
    """提取可能包含合并单元格的表格
    
    Args:
        page: pdfplumber页面对象
        table_bbox: 表格边界框 (x0, y0, x1, y1)
        
    Returns:
        表格数据
    """
    try:
        # 使用pdfplumber的表格提取功能
        table = page.crop(table_bbox).extract_table()
        if table:
            return table
        
        # 如果提取失败，尝试使用其他方法
        # 这里可以实现更复杂的表格提取逻辑
        
        return []
    except Exception as e:
        logger.error(f"提取合并单元格表格失败: {str(e)}")
        return []